/*
 * Títutlo: Aerodromo.java
 * Autor: Diego Serafín Martínez García-
 * Descripción: Se encarga de almacenar los objetos Aviones.
 * 
 * Universidad Autónoma de Yucatán
 * 
 */
package aerodromo.model;

import aerodromo.util.estructurasDatos.cola.Cola;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.FileWriter;

import aerodromo.util.estructurasDatos.cola.PriQueueList;
import aerodromo.util.estructurasDatos.deque.DequeDoubleList;
import aerodromo.util.estructurasDatos.lista.SimpleList;
import aerodromo.util.estructurasDatos.pila.StackList;


/**
 *
 * @author Diego Martínez García
 */
public class Aerodromo {
    
    
    //Uses SINGLETON DESIGN PATTERN
    private static Aerodromo currentAerodromo;
    private static int llegadasVuelos;
    private static int llegadasPasajeros;
    private static int salidasVuelos;
    private static int salidasPasajeros;

    
    public void inicializar(int aviones){
        llegadasPasajeros=0;
        llegadasVuelos=0;
        salidasPasajeros=0;
        salidasVuelos=0;
        for(int i=1; i<=aviones;i++){
        
        int Combustible = new java.util.Random().nextInt();
        if ( Combustible < 0 )
            Combustible *= -1;
        
        while(Combustible>100){
            Combustible= Combustible%100;
            
        }
        
        int Pasajeros = new java.util.Random().nextInt();
        if ( Pasajeros < 0 )
            Pasajeros *= -1;
        
        while(Pasajeros>500){
            Pasajeros/=10;
        }
        
        String matricula;
        int mat=new java.util.Random().nextInt();
        if(mat<0)
            mat*=-1;
        
        matricula=""+mat+""+(mat%1000);

        estacionamiento.insertLast(new Avion(matricula, Combustible, Pasajeros));
        llegadasPasajeros+=Pasajeros;
        llegadasVuelos++;
        
        
            System.out.println(matricula+" "+Pasajeros+" "+Combustible);
        }
    }
    
    
    
    public static Aerodromo getAerodromo(){
        if ( currentAerodromo == null ){
            System.out.println("Instancia creada");
            currentAerodromo = new Aerodromo();
        }
        return Aerodromo.currentAerodromo;
    }

    /**
     * @return the llegadasVuelos
     */
    public static int getLlegadasVuelos() {
        return llegadasVuelos;
    }

    /**
     * @param aLlegadasVuelos the llegadasVuelos to set
     */
    public static void setLlegadasVuelos(int aLlegadasVuelos) {
        llegadasVuelos = aLlegadasVuelos;
    }

    /**
     * @return the llegadasPasajeros
     */
    public static int getLlegadasPasajeros() {
        return llegadasPasajeros;
    }

    /**
     * @param aLlegadasPasajeros the llegadasPasajeros to set
     */
    public static void setLlegadasPasajeros(int aLlegadasPasajeros) {
        llegadasPasajeros = aLlegadasPasajeros;
    }

    /**
     * @return the salidasVuelos
     */
    public static int getSalidasVuelos() {
        return salidasVuelos;
    }

    /**
     * @param aSalidasVuelos the salidasVuelos to set
     */
    public static void setSalidasVuelos(int aSalidasVuelos) {
        salidasVuelos = aSalidasVuelos;
    }

    /**
     * @return the salidasPasajeros
     */
    public static int getSalidasPasajeros() {
        return salidasPasajeros;
    }

    /**
     * @param aSalidasPasajeros the salidasPasajeros to set
     */
    public static void setSalidasPasajeros(int aSalidasPasajeros) {
        salidasPasajeros = aSalidasPasajeros;
    }
    
     
    
    
    private StackList<Avion> auxiliarSalida;
    private PriQueueList<Avion> avionesEnAire;
    private DequeDoubleList<Avion> estacionamiento;
    
    private SimpleList<Operacion> log;
    
    
    
    private Aerodromo(){
        
        log = new SimpleList<Operacion>();
        
        auxiliarSalida = new StackList<Avion>();
        avionesEnAire = new PriQueueList<Avion>();
        estacionamiento = new DequeDoubleList<Avion>();
    }
    

    
    /**
     * @return the log
     */
    public SimpleList<Operacion> getLog() {
        return log;
    }

    /**
     * @param log the log to set
     */
    public void setLog(SimpleList<Operacion> log) {
        this.log = log;
    }
    
    
    
    /* 
     * Metodos de responsabilidad
     *
     * 
     * 
     * 
     */
    
        
    
    //funcion que saca el primer avion de la Queue de salida
    public boolean despegar(){
        Avion despegando= (Avion)estacionamiento.removeFirst();
        //aireATierra();
                if(aireATierra()){
            Avion nuevoAvion;
            nuevoAvion=avionesEnAire.removeMinElem();
            estacionamiento.insertLast(nuevoAvion); 
            Operacion llegada = new Operacion ( nuevoAvion, Operacion.LLEGADA );
            log.insertAtLast(llegada);
            Operacion sal = new Operacion ( despegando, Operacion.SALIDA ); 
            log.insertAtLast(sal);
            llegadasPasajeros+=nuevoAvion.getPasajeros();
            llegadasVuelos++;
            salidasPasajeros+=despegando.getPasajeros();
            salidasVuelos++;
            
            return true;
        }
                else{
        Operacion sal = new Operacion ( despegando, Operacion.SALIDA ); 
        log.insertAtLast(sal);
        salidasPasajeros+=despegando.getPasajeros();
        salidasVuelos++;
        return false;
                }
        //return despegando;
    }
    
    //funcion que saca el avion averiado, y pone a los que estan atras de el en auxiliar
    public Avion averia(Avion averiado){
        Avion o;
        while(true){
            o=(Avion)estacionamiento.removeLast();
            
            if(o.equals(averiado))
            break;
            else
                auxiliarSalida.push(o);
        }
        Operacion aver = new Operacion ( averiado, Operacion.RETIRADA ); 
        log.insertAtLast(aver);
        
        
        return averiado;
    }
    
    //funcion que pasa los de la pila auxiliar a las salida
    public void regresarASalida(){
        while(!auxiliarSalida.isEmpty()){
            estacionamiento.insertLast(auxiliarSalida.pop());
        }
    }
    
    //cuando llega un avion al espacio aereo, se agrega a la cola y si hay espacio uno baja;
    public boolean avionesEnVuelo(Avion o){
        avionesEnAire.insertItem(o, o.getCombustible());
        if(aireATierra()){
            Avion nuevoAvion;
            nuevoAvion=avionesEnAire.removeMinElem();
            estacionamiento.insertLast(nuevoAvion); 
            Operacion llegada = new Operacion ( nuevoAvion, Operacion.LLEGADA );
            log.insertAtLast(llegada);
            llegadasVuelos++;
            llegadasPasajeros+=nuevoAvion.getPasajeros();
           
            return true;
        }
        
          return false;
       // System.out.println( "agregado " + o.getMatricula() + " " + o.getCombustible() + " " + o.getPasajeros());
    }
    
    //Este metodo se usa para bajar a los aviones a tierra
    public boolean aireATierra(){
        if(estacionamiento.size()<16 && !avionesEnAire.isEmpty()){
                //estacionamiento.insertLast(avionesEnAire.removeMinElem());
                return true;
        }
        else
            return false;
    }
    
    
    
    //Escritura de archivo a disco
      public void guardar( String log ) throws FileNotFoundException, IOException{
    
          PrintWriter pw = new PrintWriter( new FileWriter( "log.txt") );
          
          for ( int i = 0; i < log.length(); i++ ){
              if ( log.charAt(i) == '\n' )
                  pw.println();
              else
                  pw.print( log.charAt(i) );
          }
          
          pw.close();
      
      }
      
      
      
      
      
      
      
      public static void main(String[] args){
        Aerodromo av = new Aerodromo();
        av.avionesEnVuelo(new Avion("Hola",123,123));
        av.avionesEnVuelo(new Avion("Adios",321,312));
        //av.despegar();
        av.inicializar(100);
        //av.guardar(av.despegar());
        //av.guardar(av.despegar());
        
    }

    
    
       
} //fin clase Aerodromo
